package com.sino.gateway.config;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.oauth2.server.resource.web.server.ServerBearerTokenAuthenticationConverter;
import org.springframework.security.web.server.SecurityWebFilterChain;

import com.sino.gateway.component.AuthConstant;
import com.sino.gateway.component.AuthorizationManager;
import com.sino.gateway.component.ParseOnlyJWTProcessor;
import com.sino.gateway.component.RestAuthenticationEntryPoint;
import com.sino.gateway.component.RestfulAccessDeniedHandler;

import cn.hutool.core.util.ArrayUtil;
import reactor.core.publisher.Mono;

/**
 * 资源服务器配置
 * Created by macro on 2020/6/19.
 */
@Configuration
@EnableWebFluxSecurity
public class ResourceServerConfig {
	
	private static final Logger log = LogManager.getLogger();
	
	
	@Autowired
    private  AuthorizationManager authorizationManager;
	@Autowired
	private  IgnoreUrlsConfig ignoreUrlsConfig;
	@Autowired
	private  RestfulAccessDeniedHandler restfulAccessDeniedHandler;
	@Autowired
	private  RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    	ServerBearerTokenAuthenticationConverter btoke = new ServerBearerTokenAuthenticationConverter();
    	btoke.setAllowUriQueryParameter(true);
    	
    	http.oauth2ResourceServer()
    			.accessDeniedHandler(restfulAccessDeniedHandler)//处理未授权
    			.authenticationEntryPoint(restAuthenticationEntryPoint)//处理未认证
    			.bearerTokenConverter(btoke)
    			.jwt()
    			.jwtDecoder(new NimbusReactiveJwtDecoder(new ParseOnlyJWTProcessor()))
    			.jwtAuthenticationConverter(jwtAuthenticationConverter())
    			;
    	

    	
        http.authorizeExchange()
                .pathMatchers(ArrayUtil.toArray(ignoreUrlsConfig.getUrls(),String.class)).permitAll()//白名单配置
                .anyExchange().access(authorizationManager)//鉴权管理器配置
                .and()
                	.exceptionHandling()
	                .accessDeniedHandler(restfulAccessDeniedHandler)//处理未授权
	                .authenticationEntryPoint(restAuthenticationEntryPoint)//处理未认证
                .and()
                	.csrf().disable()
                ;
        		
        
        
        return http.build();
    }

    @Bean
    public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        jwtGrantedAuthoritiesConverter.setAuthorityPrefix(AuthConstant.AUTHORITY_PREFIX);
        jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(AuthConstant.AUTHORITY_CLAIM_NAME);
        
        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
        return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
    }
    
    
    

    
}